/*
 * ArrayList.cpp
 *
 *  Created on: Apr 25, 2011
 *      Author: nathanielclinger
 */

#ifndef ARRAYLIST_CPP_
#define ARRAYLIST_CPP_

#ifndef ARRAYLIST_HPP_
#include "ArrayList.hpp"
#endif

#include <iostream>
#include <fstream>

template <class T>
ArrayList<T>::ArrayList()	// default constructor
{
	current = 0 ;	// set current to 0
	top = 10 ;		// set max size to 10
	al = new T[top] ;	// allocate 10 memory locations of generic type T
}

template <class T>
ArrayList<T>::ArrayList( ArrayList<T> &other )	//reference constructor
{
	current = other.current ;	// copy over the values from other
	top = other.top ;
	al = new T[top] ;
	for( int i = 0 ; i < other.current ; i++ )
		al[i] = other.al[i] ;
}

template <class T>
ArrayList<T>::ArrayList( const ArrayList<T> &other )	// ref constructor for const filed
{
	current = other.current ;	// copy over values from other
	top = other.top ;
	al = new T[top] ;
	for( int i = 0 ; i < other.current ; i++ )
		al[i] = other.al[i] ;
}

template <class T>
ArrayList<T>::~ArrayList()	// destructor simply calls the empty function
{
	empty() ;
}

template <class T>
void ArrayList<T>::empty()
{
	delete [] al ;	// delete the array pointer

	current = 0 ;	// set values to 0
	top = 0 ;
}

template <class T>
void ArrayList<T>::add( T &ob )	// add an object of type T to array by reference
{
	if( current >= top )		// if we've reached the end of the array allocate more memory
		memoryAllocator( al, &top ) ;

	al[current] = ob ;	// add object to array

	current++ ;
}

template <class T>
void ArrayList<T>::clear()	// remove all values from array, and reset to size 10
{
	empty() ;
	current = 0 ;
	top = 10 ;
	al = new T[top] ;
}

template <class T>
bool ArrayList<T>::isEmpty()	// check if array is empty
{
	if( current > 0 )
		return false ;
	else
		return true ;
}

template <class T>
T& ArrayList<T>::get( int n )	// return element n from array
{
	return al[n] ;
}

template <class T>
void ArrayList<T>::set( T &ob, int n )	// set element T in position n, copying over any other object there
{
	if( current >= n )
		al[n] = ob ;
}

template <class T>
int ArrayList<T>::length()	// get the size of the array
{
	return current ;
}

template <class T>
void ArrayList<T>::insert( T &ob, int n )	// insert an element in position n, moving all elements to the right up by one
{
	current++ ;
	if( current >= top )		// if we've reached the end of the array allocate more memory
		memoryAllocator( al, &top ) ;

	T * temp = new T[top] ;	// create a new temp array

	for( int i = 0 ; i < current ; i++ )	// copy over all the elements
	{
		if( i < n )
			temp[i] = al[i] ;		// first all elements up to n
		else if( i == n )
			temp[i] = ob ;			// then copy over the new element
		else
			temp[i] = al[i-1] ;		// then copy all the other elements over
	}

	al = temp ;
}

template <class T>
bool ArrayList<T>::find( T &ob )	// check if element ob is in array
{
	for( int i = 0 ; i < current ; i++ )
		if( al[i].equals( ob ) )	// go through the list and see if anything equals ob
			return 1 ;

	return 0 ;	// if nothing equals ob return 0
}

template <class T>
void ArrayList<T>::print()	// print out all elements in array
{
	for( int i = 0 ; i < current ; i++ )
		al[i].print() ;
}

template <class T>
void ArrayList<T>::load( char *p )		// load elements from file p
{
	ifstream file ;
	file.open( p ) ;	// open file named p
	char str[2048] ;	// create a char array of size 2048

	if( file.is_open() )	// check that file is open
	{
		while( !file.eof() )	// while we are not at end of file keep copying
		{
			file.getline( str, 2048 ) ;	// copy line by line the text from the file
			T s( str ) ;				// for each line create a new object of type T
			add( s ) ;					// and place T in the array
		}
	}
	file.close() ;	// close file
}

template <class T>
void ArrayList<T>::save( char *p )	// save this to file named p
{
	ofstream file ;
	file.open( p ) ;	// open file named p

	for( int i = 0 ; i < current ; i++ )
		file << al[i].getstring() << endl ;	// for every element in this copy to file

	file.close() ;	// close file
}

template <class T>
void ArrayList<T>::memoryAllocator( T * p, int * n )
{
	*n = (*n)*2 ;	// multiply the value at the address passed by n, and store it at that same address.
	T * temp = new T[*n] ;		// allocate a temp array of the size of the new n
	for( int i = 0 ; i < *n ; i++ )
		temp[i] = p[i] ;			// copy over the inputs from p

	p = temp ;						// set p pointer to temp
}

#endif /* ARRAYLIST_CPP_ */
